home *** CD-ROM | disk | FTP | other *** search
- Program Page2;
-
- (*---------------------------------------------------------------------------*)
- (* *)
- (* PAGE2 Version 1.0 *)
- (* *)
- (* A generic program to print text on both sides of the paper *)
- (* *)
- (* by: R. P. Byrne June 4, 1988 *)
- (* *)
- (*---------------------------------------------------------------------------*)
- (* *)
- (* I have placed this program and it's source code into the public *)
- (* domain in the hope that it may prove useful to someone other than *)
- (* myself. *)
- (* *)
- (* Please feel free to distribute this program by any means available. I *)
- (* only ask, as a courtesy, that the program not be distributed without *)
- (* the inclusion of the source code and the accompanying documentation *)
- (* file. *)
- (* *)
- (* Since this program is truly public domain software, if you paid *)
- (* someone more than $5.00 to receive it, you've probably been ripped *)
- (* off. *)
- (* *)
- (* rpb *)
- (* 6/4/88 *)
- (* *)
- (*---------------------------------------------------------------------------*)
- (* *)
- (* Usage: Page2 filename [options] [output filename] *)
- (* *)
- (* Allowable options are: *)
- (* *)
- (* /W# - Specify the width in characters (#) of your paper *)
- (* *)
- (* /L# - Specify the length in lines (#) of your paper *)
- (* *)
- (* /M# - Set a "Gutter" margin of # characters for every page. A *)
- (* gutter margin (sometimes called a "binding" margin) is *)
- (* on that prints on the left edge of odd numbered pages *)
- (* and on the right edge of even numbered pages. *)
- (* *)
- (* /F - Toggle the printing of formfeed characters between pages *)
- (* *)
- (* /E - Toggle which pages get printed first (even or odd) *)
- (* *)
- (* /N - Toggle the printing of the filename in a running header *)
- (* *)
- (* /P - Toggle the printing of page numbers in a running header *)
- (* *)
- (* /D - Toggle the printing of the current date in a running *)
- (* header *)
- (* *)
- (* Each option must be specified separately and must begin with a '/'. *)
- (* Options may be specified anywhere on the command line. *)
- (* *)
- (* You may override the selection of the DOS StdPrn device for output *)
- (* by specifying a second filename on the command line. The program *)
- (* takes the first argument not preceded by a forward slash as the *)
- (* file to be printed. Any other such parameter encountered is assumed *)
- (* to be an output file specification. All printer output is directed *)
- (* to this file if specified. *)
- (* *)
- (* The program automatically handles Tab expansion, Carriage Returns *)
- (* with no corresponding Line Feed, Line Feeds with no corresponding *)
- (* Carriage Return, embedded Backspace and Form Feed characters. *)
- (* *)
- (* Input lines longer than the available paper width will be truncated. *)
- (* *)
- (*---------------------------------------------------------------------------*)
-
- Uses Crt,
- Dos,
- StrProcs;
-
- Type
- IntPtr = ^LongInt; { Pointer type for PageTable array }
- TableRec = Record
- PageOfs : LongInt;
- PageSize : Word;
- end;
-
- Const
- BS = #008;
- TAB = #009;
- LF = #010; { Some ASCII character values }
- FF = #012;
- CR = #013;
- SPACE = #032;
-
- BufSize = 8192;
- PageLimit = 1000; { Arbitrary program limit on document size }
-
- Const { Structured }
-
- PatchArea : String[16] = 'Patch Area Start'; { Marker for CFG program }
- CPL : Word = 80; { Default Characters per Line setting }
- LPP : Word = 66; { Default Lines per Page setting }
- BindMar : Word = 0; { Default gutter margin setting }
- UseFF : Boolean = FALSE; { No Formfeeds }
- OddFirst : Boolean = TRUE; { Print odd pages first }
- PrintName : Boolean = FALSE; { No filename in page headers }
- PrintDate : Boolean = FALSE; { No current date in page headers }
- PrintPgNo : Boolean = FALSE; { No page number in page headers }
- EndPatch : String[14] = 'Patch Area End'; { Marker for CFG program }
-
- Handle : Word = 4; { handle of output file/device (4 = stdprn) }
-
- Var
- InFile : File; { The file variable for the input }
- InFileName : String; { The name of the file to be printed }
- InFileSize : LongInt; { The size of the file to be printed (bytes)}
- EOF_InFile : Boolean; { End of File indicator }
- InBuf : Array[1..BufSize] of Char; { Input buffer space }
- InBufIdx : Word; { An index for the input buffer }
- BytesIn : Word; { Count of bytes transferred at last read request }
-
- OutFileName : String; { optional output file override }
- OutFile : File; { untyped file var for output }
- OutFileHandle : Word Absolute OutFile; { handle of output file }
-
- TurboInt24 : Pointer; { storage for Turbo Pascal's Int24 addr. }
-
- PageTable : Array[1..PageLimit] of ^TableRec; { Page description table }
-
- PageCount : Word;
- SheetCount : Word;
- LineCount : LongInt; { Statistics on what gets printed }
-
- CurrentPage : Word;
- CurrentLine : Word;
- CurrentChar : Word; { Status trackers }
-
- CurrentMar : Word; { Page specific margin setting now in use }
- CurrentCPL : Word; { Page specific CPL setting now in use }
-
- PrintHdr : Boolean; { running header print flag }
- PageHdr : String; { Space to store running page header }
- HdrName : String[12]; { Space to store filename for page hdr }
- HdrDate : String[18]; { Space to store current date for page hdr }
- HdrPage : String[5]; { Space to store page no. text for pg. hdr }
-
- MsgX, MsgY : Word; { Cursor position placeholders }
-
- { --------------------------------------------------------------------------- }
- { Houskeeping routines ... }
- { --------------------------------------------------------------------------- }
-
- Procedure Abort(ErrMsg : String);
- Begin
- If ErrMsg <> '' then begin
- Writeln;
- Writeln(ErrMsg);
- Writeln;
- end {if};
- Halt(255);
- End {Abort};
-
- { --------------------------------------------------------------------------- }
-
- Procedure Syntax;
- Begin
- TextColor(LightCyan);
- TextBackground(Black);
- ClrScr;
- Writeln;
- Writeln(' Usage: Page2 filename [options]');
- Writeln;
- Writeln(' Allowable options are:');
- Writeln;
- Writeln(' /W# - Set page Width to # characters [default = ', IntStr(CPL, 0), ']');
- Writeln(' /L# - Set page Length to # lines [default = ', IntStr(LPP, 0), ']');
- Writeln(' /M# - Set a gutter Margin of # characters [default = ', IntStr(BindMar,0), ']');
- Writeln;
- Writeln(' The following options ay be toggled from one setting to another:');
- Writeln;
- Writeln(' /F - Toggle the printing of formfeed characters at the end of each page');
- Write(' [default is ');
- If UseFF then
- Writeln('ON]')
- Else
- Writeln('OFF]');
- Writeln(' /E - Toggle which pages get printed first (ie. even or odd)');
- Write(' [default is to print the ');
- If OddFirst then
- Write('odd')
- else
- Write('even');
- Writeln(' pages first]');
- Writeln;
- Writeln(' The following option toggles constitute a running page header definition.');
- Writeln(' If all options are toggled OFF, no page headers will be printed.');
- Writeln;
- Write(' /N - Include file Name in headers toggle [default = ');
- If PrintName then
- Writeln('ON]')
- else
- Writeln('OFF]');
- Write(' /D - Include current Date in headers toggle [default = ');
- If PrintDate then
- Writeln('ON]')
- else
- Writeln('OFF]');
- Write(' /P - Include Page numbers in headers toggle [default = ');
- If PrintPgNo then
- Writeln('ON]')
- else
- Writeln('OFF]');
- Abort('');
- End {Syntax};
-
- { --------------------------------------------------------------------------- }
-
- Procedure Parse_Command_Line;
- Var
- CmdLine : ^String;
- Token : String;
- I : Word;
- Code : Integer;
- Begin
- If ParamCount < 1 then
- Syntax;
- CmdLine := Ptr(PrefixSeg, $80); { set up pointer to command line in psp }
- InFileName := '';
- OutFileName := '';
- While CmdLine^ <> '' do begin
- Token := GetToken(CmdLine^, TRUE);
- If (Token[1] in ['-', '/']) then begin { Option switch character }
- Delete(Token, 1, 1); { Strip the switch character }
- If Token <> '' then { Anything left? }
- Case Token[1] of
- 'W' : Begin { Page width override }
- Delete(Token, 1, 1);
- If Token <> '' then begin
- Val(Token, CPL, Code);
- If Code <> 0 then
- Abort('Invalid page width entered!');
- end {if};
- end {'W'};
- 'L' : Begin { Page length override }
- Delete(Token, 1, 1);
- If Token <> '' then begin
- Val(Token, LPP, Code);
- If Code <> 0 then
- Abort('Invalid page length entered!');
- end {if};
- end {'L'};
- 'M' : Begin { Gutter margin override }
- Delete(Token, 1, 1);
- Val(Token, BindMar, Code);
- If Code <> 0 then
- Abort('Invalid binding margin entered!');
- end;
- 'E' : OddFirst := Not OddFirst; { First Pass toggle }
- 'F' : UseFF := Not UseFF; { Formfeed toggle }
- 'N' : PrintName := Not PrintName; { Header content override }
- 'D' : PrintDate := Not PrintDate;
- 'P' : PrintPgNo := Not PrintPgNo;
- end {case};
- end {if}
- else
- If InFileName = '' then { 1st name is file to prt }
- InFileName := Token
- else
- If OutFileName = '' then begin { 2nd name is printfile }
- OutFileName := Token;
- end {then}
- else
- Abort('Unexpected command line argument encountered!');
- end {while};
-
- End {Parse_Command_Line};
-
- { --------------------------------------------------------------------------- }
-
- Procedure Prog_Init;
- Var
- SearchBuf : SearchRec; { Buffer for Find First/Next DOS functions }
- Attribute : Word;
- Regs : Registers;
- Begin
- With Regs do begin
- AH := $35;
- AL := $24;
- MsDos(Regs);
- TurboInt24 := Ptr(ES, BX);
- end {with};
-
- Attribute := ReadOnly or Hidden or SysFile or Archive;
- FindFirst(InFileName, Attribute, SearchBuf);
- If DosError <> 0 then
- Abort('Could not locate file [' + InFileName + ']!');
- Assign(InFile, InFileName);
-
- If OutFileName <> '' then begin
- Assign(OutFile, OutFileName);
- Rewrite(OutFile, 1);
- Handle := OutFileHandle;
- end {if};
-
- PrintHdr := (PrintName or PrintDate or PrintPgNo);
- If PrintName then
- HdrName := NameOnly(InFileName)
- else
- HdrName := '';
- If PrintDate then
- HdrDate := DateStr
- else
- HdrDate := '';
- If PrintPgNo then
- HdrPage := 'Page '
- else
- HdrPage := '';
-
- TextColor(Yellow);
- TextBackground(Black);
- ClrScr;
- Writeln;
- Writeln('Page2 - Generic 2-sided print utility - by R. P. Byrne 5/24/88');
- Writeln;
- TextColor(LightGreen);
- Writeln('Options in effect are');
- Writeln;
- Writeln(' Page width : ', CPL);
- Writeln(' Page length : ', LPP);
- Writeln(' Gutter margin : ', BindMar);
- Write(' Formfeeds : ');
- If UseFF then
- Writeln('On')
- else
- Writeln('Off');
- Write(' First printing : ');
- If OddFirst then
- Writeln('Odd pages')
- else
- Writeln('Even pages');
- Write(' Page headers : ');
- If PrintHdr then begin
- If PrintName then
- Write('Filename ');
- If PrintDate then
- Write('Date ');
- If PrintPgNo then
- Write('Page Numbers ');
- Writeln;
- end {then}
- else
- Writeln('None');
-
- TextColor(Yellow);
- TextBackground(Black);
-
- End {Prog_Init};
-
- { --------------------------------------------------------------------------- }
- { Ok, here are the routines that do the work ... }
- { --------------------------------------------------------------------------- }
-
- Procedure Read_Input;
- Begin
- EOF_InFile := FALSE;
- BlockRead(InFile, InBuf, SizeOf(InBuf), BytesIn);
- InBufIdx := 0;
- If BytesIn = 0 then
- EOF_InFile := TRUE;
- End {Read_Input};
-
- { --------------------------------------------------------------------------- }
-
- Procedure NewPage;
- Begin
- Inc(CurrentPage);
- If CurrentPage > PageLimit then
- Abort('Too many pages to print. Maximum is ' + IntStr(PageLimit, 0) + '!');
-
- LineCount := LineCount + CurrentLine;
- CurrentLine := 0;
- CurrentChar := 0;
-
- If PrintHdr then
- Inc(CurrentLine, 2);
-
- If (MemAvail < (SizeOf(IntPtr) + 128)) then
- Abort('Insufficient memory to process file!');
- New(PageTable[CurrentPage]);
-
- PageTable[CurrentPage]^.PageOfs := FilePos(InFile) - BytesIn + InBufIdx;
- PageTable[CurrentPage]^.PageSize := 0;
- If CurrentPage > 1 then
- PageTable[Pred(CurrentPage)]^.PageSize :=
- PageTable[CurrentPage]^.PageOfs -
- PageTable[Pred(CurrentPage)]^.PageOfs;
- End {NewPage};
-
- { --------------------------------------------------------------------------- }
-
- Procedure Scan_Input;
- Var
- I : Word;
- NewPageAddr : Pointer; { Address of NewPage procedure }
- Begin
- Writeln;
- Writeln('Scanning input file ... Please wait');
- Reset(InFile, 1);
- InFileSize := FileSize(InFile);
- Read_Input;
- PageCount := 0; LineCount := 0;
- CurrentPage := 0; CurrentLine := 0; CurrentChar := 0;
- NewPageAddr := @NewPage;
- NewPage;
- While (Not EOF_InFile) do begin
- Inline(
- $8B/$0E/>BYTESIN/ { mov cx,[>BytesIn] ; Loop thru all bytes read}
- $8D/$36/>INBUF/ { lea si,[>InBuf] ; ds:si points to the buffer}
- $AC/ {ScanLoop: lodsb ; get one char from buffer}
- $56/ { push si ; need to keep track of index into}
- $89/$F7/ { mov di,si ; input buffer for file offset}
- $8D/$36/>INBUF/ { lea si,[>InBuf] ; calculations in NewPage proc.}
- $29/$F7/ { sub di,si ; DI now has this index value.}
- $89/$3E/>INBUFIDX/ { mov [>InBufIdx],di ; Store it for later use.}
- $5E/ { pop si ; and restore our pointer}
- $3C/$08/ { cmp al,8 ; a backspace?}
- $74/$1A/ { jz Backspace ; yup, go to it.}
- $3C/$09/ { cmp al,9 ; a tabby?}
- $74/$25/ { jz HorizTab ; yup}
- $3C/$0A/ { cmp al,10 ; a linefeed?}
- $74/$2D/ { jz NewLine ; yup}
- $3C/$0C/ { cmp al,12 ; a formfeed?}
- $74/$2F/ { jz NewPage ; yup}
- $3C/$0D/ { cmp al,13 ; a carriage return?}
- $74/$37/ { jz CR ; yup}
- $3C/$20/ { cmp al,' ' ; is it a "non-control" char?}
- $72/$46/ { jb GetNext ; no ... ignore it}
- $FF/$06/>CURRENTCHAR/ {LegalChar: inc word [>CurrentChar] ; increment our character count}
- $EB/$36/ { jmp short ChkLimits ; and go check our counters}
- $8B/$1E/>CURRENTCHAR/ {BackSpace: mov bx,[>CurrentChar]}
- $83/$FB/$00/ { cmp word bx,0 ; do we have any other chars yet?}
- $76/$37/ { jbe GetNext ; no ... ignore it}
- $FF/$0E/>CURRENTCHAR/ { dec word [>CurrentChar] ; yes ... decrement char count}
- $EB/$31/ { jmp short GetNext ; and go get next character}
- $83/$06/>CURRENTCHAR/$08/ {HorizTab: add word [>CurrentChar],8 ; advance counter to next}
- $83/$26/>CURRENTCHAR/$F8/ { and word [>CurrentChar],$FFF8 ; tab stop}
- $EB/$1B/ { jmp short ChkLimits ; and go check counter limits}
- $FF/$06/>CURRENTLINE/ {NewLine: inc word [>CurrentLine] ; increment line counter,}
- $EB/$15/ { jmp short ChkLimits ; and go check counter limits}
- $50/ {NewPage: push ax ; Ok, time to start a new page}
- $51/ { push cx ; call the NewPage procedure}
- $56/ { push si}
- $FF/$96/>NEWPAGEADDR/ { Call [bp+>NewPageAddr] ; settings}
- $5E/ { pop si}
- $59/ { pop cx}
- $58/ { pop ax}
- $EB/$13/ { jmp short GetNext}
- $BB/$00/$00/ {CR: mov bx,0}
- $89/$1E/>CURRENTCHAR/ { mov [>CurrentChar],bx ; adjust character counter}
- $EB/$0A/ { jmp short GetNext}
- $8B/$16/>CURRENTLINE/ {ChkLimits: mov dx,[>CurrentLine]}
- $3B/$16/>LPP/ { cmp dx,[>LPP]}
- $73/$E1/ { jae NewPage}
- $49/ {GetNext: dec cx}
- $E3/$02/ { jcxz Done}
- $EB/$8E); { jmp ScanLoop}
- {Done:}
- Read_Input;
- end {While};
-
- NewPage; { Close out the current page }
-
- PageCount := Pred(CurrentPage);
- SheetCount := Round(PageCount / 2.0);
-
- Writeln;
- Writeln(' Total lines to be printed: ', LineCount);
- Writeln(' Total pages to be printed: ', PageCount);
- Writeln(' Total sheets of paper required: ', SheetCount);
- Writeln;
-
- End {Scan_Input};
-
- { --------------------------------------------------------------------------- }
-
- Procedure Print(Msg : String);
- { Print a message on the printer }
- Begin
- Inline(
- $1E/ { push ds ; Save our data seg.}
- {;}
- {; Set the Critical Error Interrupt vector to}
- {; point back at the DOS handler whose address is}
- {; stored in the global system variable SaveInt24}
- {;}
- $C5/$16/>SAVEINT24/ { lds dx,[>SaveInt24]}
- $B4/$25/ { mov ah,$25}
- $B0/$24/ { mov al,$24}
- $CD/$21/ { int $21}
- {;}
- {; Ok, write the buffered data to the device}
- {;}
- $1F/ { pop ds ;Restore the "real" data seg}
- $1E/ { push ds ;and save back to the stack}
- $8B/$1E/>HANDLE/ { mov bx,[>Handle]}
- $8C/$D0/ { mov ax,ss}
- $8E/$D8/ { mov ds,ax}
- $8D/$96/>MSG/ { lea dx,[bp+>Msg]}
- $42/ { inc dx}
- $31/$C9/ { xor cx,cx}
- $8A/$8E/>MSG/ { mov byte cl,[bp+>Msg]}
- $B4/$40/ { mov ah,$40}
- $CD/$21/ { int $21}
- {;}
- {; Restore the Critical Error interrupt vector}
- {; to point back at Turbo Pascal's handler.}
- {; The address of Turbo's routine was previously}
- {; stored in the global pointer variable TurboInt24}
- $C5/$16/>TURBOINT24/ { lds dx,[>TurboInt24]}
- $B4/$25/ { mov ah,$25}
- $B0/$24/ { mov al,$24}
- $CD/$21/ { int $21}
- {;}
- $1F); { pop ds ; Restore the data seg.}
-
- End {Print};
-
- { --------------------------------------------------------------------------- }
-
- Procedure Init_Page;
- Var
- PgNo : String[4];
- Begin
- If (CurrentPage AND $0001) <> 0 then { if odd page number }
- CurrentMar := BindMar
- else
- CurrentMar := 0;
-
- CurrentCPL := CPL - BindMar;
-
- GotoXY(MsgX, MsgY);
- ClrEol;
- Write(CurrentPage);
-
- If (CurrentPage > 2) And UseFF then
- Print(FF);
-
- Print(Copies(' ', CurrentMar));
-
- If PrintPgNo then
- PgNo := IntStr(CurrentPage, 0)
- else
- PgNo := '';
-
- If (CurrentPage AND $0001) <> 0 then begin { if odd page number }
- PageHdr := HdrName;
- PageHdr := PageHdr +
- Copies(' ', ((CurrentCPL - Length(HdrDate)) DIV 2) - Length(PageHdr)) +
- HdrDate;
- PageHdr := PageHdr +
- Copies(' ', CurrentCPL - Length(PageHdr) - Length(HdrPage) - Length(PgNo)) +
- HdrPage + PgNo;
- end {then}
- else begin
- PageHdr := HdrPage + PgNo;
- PageHdr := PageHdr +
- Copies(' ', ((CurrentCPL - Length(HdrDate)) DIV 2) - Length(PageHdr)) +
- HdrDate;
- PageHdr := PageHdr +
- Copies(' ', CurrentCPL - Length(PageHdr) - Length(HdrName)) +
- HdrName;
- end {if};
-
- If PrintHdr then begin
- Print(PageHdr);
- (*
- If you want your page header underlined, remove the comment
- markers around the following statement. Note that your printer
- must be able to handle a standalone carriage return for this
- to work properly (the printhead should move to the first print
- position without advancing to the next printline).
-
- Print(CR + Copies(' ', CurrentMar) + Copies('_', Length(PageHdr)));
- *)
-
- Print(CR + LF + CR + LF);
- Print(Copies(' ', CurrentMar));
- CurrentLine := 2;
- end {then}
- else
- CurrentLine := 0;
-
- CurrentChar := 0;
-
- End {Init_Page};
-
- { --------------------------------------------------------------------------- }
-
- Procedure PrintPage;
- Var
- PrintAddr : Pointer;
- ReadAddr : Pointer;
- LMar : String;
- PrtString : String;
- Begin
- Seek(InFile, PageTable[CurrentPage]^.PageOfs);
- Read_Input;
- Init_Page; { initialize Line counter & optionally print page headers }
- PrintAddr := @Print;
- ReadAddr := @Read_Input;
- LMar := Copies(' ', CurrentMar);
- Inline(
- {; Set the Critical Interrupt vector to point back}
- {; at the DOS handler whose address is stored}
- {; in the global system variable SaveInt24}
- $1E/ { push ds}
- $C5/$16/>SAVEINT24/ { lds dx,[>SaveInt24]}
- $B4/$25/ { mov ah,$25}
- $B0/$24/ { mov al,$24}
- $CD/$21/ { int $21}
- $1F/ { pop ds}
- {;}
- $E9/$1F/$00/ {SkipProcs: jmp EntryPt}
- {;}
- {;}
- {BuffCheck:}
- {;}
- {; On entry to this subroutine, it is assumed that DS:SI is pointing to}
- {; somewhere inside the file input buffer.}
- {;}
- $56/ { push si ;save si}
- $57/ { push di ;save di}
- $89/$F7/ { mov di,si}
- $8D/$36/>INBUF/ { lea si,[>InBuf]}
- $29/$F7/ { sub di,si}
- {;}
- {; the next two statements will need a manual fix-up after being}
- {; assembled with Baldwin's Inline program (version 2.19 - 4/26/88).}
- {; Dave's assembler will generate the following code:}
- {; $90/}
- {; $83/$FF/<BufSize}
- {; patch the resulting OBJ file by removing the NOP instruction}
- {; (ie. erase the $90/) and change the compare instruction to:}
- {; $81/$FF/>BufSize}
- {;}
- { nop}
- $81/$FF/>BUFSIZE/ { cmp word di,>BufSize ;time to read more data?}
- $5F/ { pop di}
- $5E/ { pop si}
- $76/$0C/ { jbe NoRead ; ... not yet}
- $51/ { push cx ;save loop counter}
- $57/ { push di}
- $FF/$96/>READADDR/ { call [bp+>ReadAddr] ;read data into buffer}
- $5F/ { pop di}
- $59/ { pop cx ;restore loop counter}
- $8D/$36/>INBUF/ { lea si,[>InBuf] ;DS:SI points to input buffer}
- $C3/ {NoRead: ret ;Return to caller}
- {;}
- {;}
- $8D/$36/>PAGETABLE/ {EntryPt: lea si,[>PageTable]}
- $A1/>CURRENTPAGE/ { mov ax,[>CurrentPage]}
- $48/ { dec ax}
- $D1/$E0/ { shl ax,1}
- $D1/$E0/ { shl ax,1}
- $01/$C6/ { add si,ax}
- $C4/$3C/ { les di,[si] ;ES:DI points to pagetable entry}
- $26/$8B/$4D/$04/ { es: mov cx,[di+4] ;CX now has pagesize in bytes}
- $8D/$36/>INBUF/ { lea si,[>InBuf] ;DS:SI points to input buffer}
- $8C/$D0/ { mov ax,ss}
- $8E/$C0/ { mov es,ax}
- $8D/$BE/>PRTSTRING/ { lea di,[bp+>PrtString] ;ES:DI --> String to be built & printed}
- $B0/$00/ { mov al,0}
- $AA/ { stosb ;store 0 in the length byte}
- {;}
- $E8/$BB/$FF/ {Looper: call BuffCheck ;make sure buffer isn't empty}
- $AC/ { lodsb ;get a byte from the buffer}
- $3C/$08/ { cmp al,8 ;backspace?}
- $75/$16/ { jnz LineFeed ;no, go check for other char types}
- $83/$3E/>CURRENTCHAR/$00/ { cmp word [>CurrentChar],0 ;anything to backspace over?}
- $75/$03/ { jnz Backup ;yes, process the character}
- $E9/$E0/$00/ { jmp GetNext ;no, skip it and get next char}
- $FF/$0E/>CURRENTCHAR/ {Backup: dec word [>CurrentChar] ;decrement position counter}
- $AA/ { stosb ;store the BS in the print string}
- $FE/$86/>PRTSTRING/ { inc byte [bp+>PrtString] ;and bump the length byte}
- $E9/$B0/$00/ { jmp ChkString ;go see if time to print the string}
- {;}
- $3C/$0A/ {LineFeed: cmp al,10 ;linefeed?}
- $75/$0C/ { jnz CR ;no, go check for other char types}
- $FF/$06/>CURRENTLINE/ { inc word [>CurrentLine]}
- $AA/ { stosb ;store LF in print string}
- $FE/$86/>PRTSTRING/ { inc byte [bp+>PrtString] ;bump string's length byte}
- $E9/$A0/$00/ { jmp ChkString ;go see if time to print the string}
- {;}
- $3C/$0D/ {CR: cmp al,13 ;carriage return?}
- $75/$45/ { jnz HTab ;no, go check for other char types}
- $AA/ { stosb ;store CR in print string}
- $FE/$86/>PRTSTRING/ { inc byte [bp+>PrtString] ;bump string length byte}
- $C7/$06/>CURRENTCHAR/$00/$00/ { mov word [>CurrentChar],0 ;reset current character ptr to 0}
- $83/$F9/$01/ { cmp cx,1 ;Are we at end-of-page yet?}
- $77/$03/ { ja ChkLF ;no, see if next char is linefeed}
- $E9/$89/$00/ { jmp ChkString ;Yes, skip the following code}
- $E8/$76/$FF/ {ChkLF: call BuffCheck ;make sure buffer isn't empty}
- $80/$3C/$0A/ { cmp byte [si],10 ;is next char a linefeed?}
- $75/$0F/ { jnz NoLF ;no, skip this part}
- $A4/ { movsb ;yes, put it into prtstring before margin}
- $49/ { dec cx}
- $FE/$86/>PRTSTRING/ { inc byte [bp+>PrtString] ;bump length byte}
- $FF/$06/>CURRENTLINE/ { inc word [>CurrentLine] ;increment current line counter}
- $83/$F9/$01/ { cmp cx,1}
- $76/$72/ { jbe ChkString ;if we're done with page ...}
- $51/ {NoLF: push cx ; otherwise, print a margin}
- $1E/ { push ds}
- $56/ { push si ;save our buffer pointer}
- $8C/$D0/ { mov ax,ss}
- $8E/$D8/ { mov ds,ax}
- $8D/$B6/>LMAR/ { lea si,[bp+>LMar] ;get ready to copy left margin}
- $AC/ { lodsb ; into print string}
- $98/ { cbw}
- $89/$C1/ { mov cx,ax ;byte count into cl}
- $00/$8E/>PRTSTRING/ { add [bp+>PrtString],cl ;add it to existing string length}
- $F2/$A4/ { rep movsb ;and append margin to print string}
- $5E/ { pop si}
- $1F/ { pop ds}
- $59/ { pop cx}
- $E9/$57/$00/ { jmp ChkString}
- {;}
- $3C/$09/ {HTab: cmp al,09 ;a tabby?}
- $75/$33/ { jnz CtrlChar ;no, go check for other char types}
- $8B/$1E/>CURRENTCHAR/ { mov bx,[>CurrentChar] ;get current line position}
- $83/$C3/$08/ { add bx,8 ;determine next tab stop}
- $83/$E3/$F8/ { and bx,$FFF8}
- $3B/$1E/>CURRENTCPL/ { cmp bx,[>CurrentCPL] ;past end of line yet?}
- $76/$0B/ { jbe SameLine ;not yet ...}
- $8B/$16/>CURRENTCPL/ { mov dx,[>CurrentCPL]}
- $89/$16/>CURRENTCHAR/ { mov [>CurrentChar],dx ;CurrentChar := CurrentCPL}
- $E9/$5C/$00/ { jmp GetNext}
- $53/ {SameLine: push bx}
- $2B/$1E/>CURRENTCHAR/ { sub bx,[>CurrentChar] ;bx = no. of spaces to add to print line}
- $51/ { push cx}
- $89/$D9/ { mov cx,bx}
- $B0/$20/ { mov al,' '}
- $00/$8E/>PRTSTRING/ { add [bp+>PrtString],cl}
- $F2/$AA/ { rep stosb ;space out to tab stop}
- $59/ { pop cx}
- $5B/ { pop bx}
- $89/$1E/>CURRENTCHAR/ { mov [>CurrentChar],bx}
- $EB/$20/ { jmp short ChkString ;go see if string is ready for printer}
- {;}
- $3C/$20/ {CtrlChar: cmp al,' ' ;char < ascii 32?}
- $73/$07/ { jae TxtChar ;no, must be printable ...}
- $AA/ { stosb ;add unprintable char to string}
- $FE/$86/>PRTSTRING/ { inc byte [bp+>PrtString]}
- $EB/$39/ { jmp short GetNext ; but don't bump position counter}
- {;}
- $8B/$1E/>CURRENTCHAR/ {TxtChar: mov bx,[>CurrentChar] ;get character position within line}
- $3B/$1E/>CURRENTCPL/ { cmp bx,[>CurrentCPL] ;are we at end of line yet?}
- $73/$2F/ { jae GetNext ;yes, skip this character}
- $AA/ { stosb ;no, store char in string}
- $FE/$86/>PRTSTRING/ { inc byte [bp+>PrtString]}
- $FF/$06/>CURRENTCHAR/ { inc word [>CurrentChar] ;bump position counter}
- $EB/$00/ { jmp short ChkString ;and go check length of print string}
- {;}
- $80/$BE/>PRTSTRING/$80/ {ChkString: cmp byte [bp+>PrtString],128 ;only let it grow to 128 chars or so}
- $72/$1D/ { jb GetNext}
- $51/ {PrintIt: push cx ; Save everything just in case}
- $56/ { push si}
- $57/ { push di}
- $1E/ { push ds}
- $8D/$BE/>PRTSTRING/ { lea di,[bp+>PrtString]}
- $16/ { push ss}
- $57/ { push di}
- $FF/$96/>PRINTADDR/ { call [bp+>PrintAddr] ;print the string}
- $1F/ { pop ds ;Restore all saved regs}
- $5F/ { pop di}
- $5E/ { pop si}
- $59/ { pop cx}
- $8C/$D0/ { mov ax,ss ;reset our pointer to the string}
- $8E/$C0/ { mov es,ax ; variable that holds the chars}
- $8D/$BE/>PRTSTRING/ { lea di,[bp+>PrtString] ; to be printed}
- $B0/$00/ { mov al,0 ;stuff 0 in the length byte}
- $AA/ { stosb}
- {;}
- $49/ {GetNext: dec cx ;decrement our loop counter}
- $E3/$03/ { jcxz Done ;done yet?}
- $E9/$08/$FF/ { jmp Looper ;no, go back for more}
- {;}
- $80/$BE/>PRTSTRING/$00/ {Done: cmp byte [bp+>PrtString],0 ;any leftovers?}
- $74/$0A/ { jz TimeToExit ;no, exit}
- $8D/$BE/>PRTSTRING/ { lea di,[bp+>PrtString]}
- $16/ { push ss}
- $57/ { push di}
- $FF/$96/>PRINTADDR/ { call [bp+>PrintAddr] ;print the string}
- {;}
- {TimeToExit:}
- {; Restore the Critical Error interrupt vector}
- {; to point back at Turbo Pascal's handler.}
- {; The address of Turbo's routine was previously}
- {; stored in the global pointer variable TurboInt24}
- $1E/ { push ds}
- $C5/$16/>TURBOINT24/ { lds dx,[>TurboInt24]}
- $B4/$25/ { mov ah,$25}
- $B0/$24/ { mov al,$24}
- $CD/$21/ { int $21}
- $1F); { pop ds}
-
- End {PrintPage};
-
- { --------------------------------------------------------------------------- }
-
- Procedure Print_Odd_Pages;
- Var
- LastPage : Word;
- I : Word;
- Begin
-
- If (PageCount AND $0001) = 0 then
- LastPage := Pred(PageCount)
- else
- LastPage := PageCount;
-
- CurrentPage := 1;
-
- While CurrentPage <= LastPage do begin
- PrintPage;
- Inc(CurrentPage, 2);
- end {while};
-
- If CurrentLine <= LPP then
- If UseFF then
- Print(FF)
- else
- For I := CurrentLine + 1 To LPP do
- Print(CR + LF);
-
- End {Print_Odd_Pages};
-
- { --------------------------------------------------------------------------- }
-
- Procedure Print_Even_Pages;
- Var
- LastPage : Word;
- I : Word;
- Begin
-
- If (PageCount AND $0001) = 1 then
- LastPage := Pred(PageCount)
- else
- LastPage := PageCount;
-
- CurrentPage := 2;
-
- While CurrentPage <= LastPage do begin
- PrintPage;
- Inc(CurrentPage, 2);
- end {while};
-
- If CurrentLine <= LPP then
- If UseFF then
- Print(FF)
- else
- For I := CurrentLine + 1 To LPP do
- Print(CR + LF);
-
- If (PageCount AND $0001) = 1 then
- If UseFF then
- Print(FF)
- else
- For I := 1 to LPP do
- Print(CR + LF);
-
- End {Print_Even_Pages};
-
- { --------------------------------------------------------------------------- }
-
- Var
- Ch : Char;
- Begin
- Parse_Command_Line;
- Prog_Init;
- Scan_Input;
- If OddFirst or (PageCount = 1) then
- Write('Ready to print the odd pages ... Press any key to start')
- else
- Write('Ready to print the even pages ... Press any key to start');
- Ch := Readkey;
- Writeln;
- Writeln;
- Write('Printing page number ');
- MsgX := WhereX; MsgY := WhereY;
- If OddFirst or ((Not OddFirst) and (PageCount = 1)) then
- Print_Odd_Pages
- else
- Print_Even_Pages;
-
- If PageCount > 1 then begin
- Writeln;
- Writeln;
- Writeln('Ready to print the remaining pages ...');
- Write('Turn the paper over and press any key when ready');
- Ch := ReadKey;
- Writeln;
- Writeln;
- Write('Printing page number ');
- MsgX := WhereX; MsgY := WhereY;
- If OddFirst then
- Print_Even_Pages
- else
- Print_Odd_Pages;
- end {if};
-
- Close(InFile);
- If OutFileName <> '' then
- Close(OutFile);
-
- Writeln;
- Writeln;
- Writeln('Done.');
- Writeln;
- End.
-